#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/reboot.h>
#include <errno.h>

#include "bsp.h"
#include "event.h"
#include "key.h"
#include "menu.h"
#include "parameter.h"
#include "lcd.h"
#include "ICM20948.h"
#include "hal_thermal.h"
#include "msg_thermal.h"
#include "fpga.h"

#include "log2file.h"
SDL_TimerID SDL_timer_id = NULL;

static int execute_command(const char *command, char *result) {
    FILE* fp;
    char buffer[1024];

    // 打开进程并执行命令
    fp = popen(command, "r");
    if (fp == NULL) {
        printf("Error: Failed to execute command\n");
        return -1;
    }

    // 读取命令输出
    while (fgets(buffer, 1024, fp) != NULL) {
        // 在这里你可以处理输出，例如拼接到一个字符串中
        strcat(result, buffer);
        // 这里简单地输出到屏幕
        // printf("%s", buffer);
    }

    // 关闭进程
    pclose(fp);

    return 0;
}

// sel 0：保存，1：恢复
static void save_all_parameters(int sel, UICtx_t *pobj)
{
    if (sel) {
        hal_save_para(PARA_CROSS_POS_X, 0);
        hal_save_para(PARA_CROSS_POS_Y, 0);
        hal_save_para(PARA_TM_CONTRAST, 5);
        hal_save_para(PARA_LANGUAGE, 0);
        // hal_save_para(PARA_TM_DETAIL_ENHANCE, 0);
        hal_save_para(PARA_TM_3D_DENOISE, 5);
        hal_save_para(PARA_TM_2D_DENOISE, 5);
        // hal_save_para(PARA_TM_GAMMA, 5);
        hal_save_para(PARA_TM_BRIGHTNESS, 5);
        hal_save_para(PARA_TM_SHARPNESS, 5);
        hal_save_para(PARA_TM_MIRROR, 0);
        hal_save_para(PARA_TM_FLIP, 0);
        hal_save_para(PARA_TM_EIS, 1);
        hal_save_para(PARA_RETICLE, 0);
        hal_save_para(PARA_COMPASS, 0);
        hal_save_para(PARA_MOTION, 0);
        hal_save_para(PARA_CROSS_COLOR, 0);
        if (TYPE_VIS_1920X1080 == pobj->devctx.sensor_type.val) {
            hal_save_para(PARA_VIS_MODE, 0);
            hal_save_para(PARA_EC, 6);
            hal_save_para(PARA_WDR, 1);
            hal_save_para(PARA_WB_MODE, 0);
            hal_save_para(PARA_COLOR_TEMP, 1);
        } else {
            hal_save_para(PARA_COLOR_MODE, 0);
        }
    } else {
        hal_save_para(PARA_TM_CONTRAST, pobj->devctx.img_contrast.val);
        hal_save_para(PARA_LANGUAGE, pobj->devctx.language.val);
        // hal_save_para(PARA_TM_DETAIL_ENHANCE, pobj->devctx.img_detail_enhance.val);
        hal_save_para(PARA_TM_3D_DENOISE, pobj->devctx.img_3D_denoise.val);
        hal_save_para(PARA_TM_2D_DENOISE, pobj->devctx.img_2D_denoise.val);
        // hal_save_para(PARA_TM_GAMMA, pobj->devctx.img_gamma.val);
        hal_save_para(PARA_TM_BRIGHTNESS, pobj->devctx.img_brightness.val);
        hal_save_para(PARA_TM_SHARPNESS, pobj->devctx.img_sharpness.val);
        hal_save_para(PARA_TM_MIRROR, pobj->devctx.image_miror.val);
        hal_save_para(PARA_TM_FLIP, pobj->devctx.image_flip.val);
        hal_save_para(PARA_TM_EIS, pobj->devctx.EIS.val);
        hal_save_para(PARA_RETICLE, pobj->devctx.reticle.val);
        hal_save_para(PARA_COMPASS, pobj->devctx.compass.val);
        hal_save_para(PARA_MOTION, pobj->devctx.motion.val);
        hal_save_para(PARA_CROSS_COLOR, pobj->devctx.cross_color.val);
        if (TYPE_VIS_1920X1080 == pobj->devctx.sensor_type.val) {
            hal_save_para(PARA_VIS_MODE, pobj->devctx.VIS_mode.val);
            hal_save_para(PARA_EC, pobj->devctx.EC.val);
            hal_save_para(PARA_WDR, pobj->devctx.WDR.val);
            hal_save_para(PARA_WB_MODE, pobj->devctx.WB_mode.val);
            hal_save_para(PARA_COLOR_TEMP, pobj->devctx.color_temp.val);
        } else {
            hal_save_para(PARA_COLOR_MODE, pobj->devctx.color_mode.val);
        }
    }
    save_paramemters();
}

/*
 * Idle 界面
 * 确认键长按：进入 Menu 界面。
 * 上键短按：调节图像亮度，0-10，可循环切换，在屏幕的右上角显示亮度条，3 秒后
 * 消失。
 * 上键长按：开启十字分化功能，再次长按，关闭十字分化功能，为十字分化功能的快捷键。
 * 左键短按：缩小放大倍数，4X，3X，2X，1X，可循环切换。相对应的放大倍数图标显
 * 示在屏幕左上角，2X，3X，4X，图标一直显示（1X 不显示）。
 * 右键短按：增大放大倍数，1X，2X，3X，4X，可循环切换。相对应的放大倍数图标显
 * 示在屏幕左上角，2X，3X，4X，图标一直显示（1X 不显示）。
 * 下键短按：顺序切换显示模式，黑热模式，白热模式，红热模式，蓝绿火焰，铁红，频
 * 谱，可循环切换。相对应的英文字符显示在底部，Black Hot，White Hot，Red Hot，
 * Blue-green Flames，Iron Rainbow，Spectrum 字符 3 秒后消失。（微光夜视镜头时，
 * 此按键无功能）
 * 同时短按左右键：执行此操作进行一次手动快门校正。（微光夜视镜头时，此组合键无
 * 功能）
 * 同时长按左右键：执行此操作进行一次背景快门校正。（微光夜视镜头时，此组合键无
 * 功能）
 * 其余按键操作，无功能。
 */
static int setup_normal_mainmenu1(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    if (pobj->devctx.reticle.val) {
        hal_cross_update(0, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);
    }
    pobj->curid = id_mainmenu1;

    return 0;
}

static int setup_normal_img_brightness(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.img_brightness.val++;
    if (pobj->devctx.img_brightness.val > pobj->devctx.img_brightness.max) {	
        pobj->devctx.img_brightness.val = 0;
    }
    pobj->devctx.save_para_tick.val = 25;
    pobj->devctx.img_brightness_tick.val = 15;
    switch (pobj->devctx.sensor_type.val)
    {
    case TYPE_VIS_1920X1080:
        hal_cs_set_brightness(pobj->devctx.img_brightness.val * 20);
        break;
    case TYPE_FPGA_256X192:
    case TYPE_FPGA_384X288:
    case TYPE_FPGA_640X512:
        HAL_FPGA_brightness(pobj->devctx.img_brightness.val);
        break;
    default:
        hal_thermal_set_bright(pobj->devctx.img_brightness.val);
        break;
    }

    return 0;
}

static int setup_normal_reticle(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.reticle.val = 1 - pobj->devctx.reticle.val;
    hal_cross_update(pobj->devctx.reticle.val, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);
    pobj->devctx.save_para_tick.val = 25;

    return 0;
}

static int setup_normal_zoom_dec(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    int cross_pos_x, cross_pos_y;

    pobj->devctx.zoom.val--;
    if (pobj->devctx.zoom.val < 0) {	
        pobj->devctx.zoom.val = pobj->devctx.zoom.max;
    }
    if (0 == pobj->devctx.reticle.val) {
        cross_pos_x = 0;
        cross_pos_y = 0;
    } else {
        cross_pos_x = pobj->devctx.cross_pos.center_x.val;
        cross_pos_y = pobj->devctx.cross_pos.center_y.val;
    }
    float wflag = (float)pobj->res_info.sensor_width / pobj->res_info.osd_width;
    float hflag = (float)pobj->res_info.sensor_height / pobj->res_info.osd_height;
    hal_crop_zoom(cross_pos_x, cross_pos_y, wflag, hflag, pobj->devctx.zoom.val);

    return 0;
}

static int setup_normal_zoom_inc(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    int cross_pos_x, cross_pos_y;

    pobj->devctx.zoom.val++;
    if (pobj->devctx.zoom.val > pobj->devctx.zoom.max) {	
        pobj->devctx.zoom.val = 0;
    }
    if (0 == pobj->devctx.reticle.val) {
        cross_pos_x = 0;
        cross_pos_y = 0;
    } else {
        cross_pos_x = pobj->devctx.cross_pos.center_x.val;
        cross_pos_y = pobj->devctx.cross_pos.center_y.val;
    }
    float wflag = (float)pobj->res_info.sensor_width / pobj->res_info.osd_width;
    float hflag = (float)pobj->res_info.sensor_height / pobj->res_info.osd_height;
    hal_crop_zoom(cross_pos_x, cross_pos_y, wflag, hflag, pobj->devctx.zoom.val);

    return 0;
}

static int setup_normal_color_mode(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.save_para_tick.val = 25;
    pobj->devctx.color_mode_tick.val = 15;
    switch (pobj->devctx.sensor_type.val)
    {
    case TYPE_VIS_1920X1080:
        pobj->devctx.VIS_mode.val++;
        if (pobj->devctx.VIS_mode.val > pobj->devctx.VIS_mode.max) {
            pobj->devctx.VIS_mode.val = 0;
        }
        switch (pobj->devctx.VIS_mode.val)
        {
        case 0: // 白天模式 50hz 探测器自动调节50hz
            if(pobj->devctx.rec.val > 0) {
                pobj->devctx.VIS_sensor_fps.val = 25;
            } else {
                pobj->devctx.VIS_sensor_fps.val = 50;
            }
            freezetime_msg_send(125);//冻结时间按照星光帧率计算
            hal_cs_set_monomode2(0);
            hal_cs_set_awb(0);
            hal_cs_set_capmode(1, pobj->devctx.VIS_sensor_fps.val);   
            hal_cs_set_shutter(40000, pobj->devctx.VIS_sensor_fps.val);
            hal_cs_set_adgain(1000, 384000);
            IRCUT_modle(0);
            break;
        case 1: //星光模式 25hz 探测器自动调节12hz
            pobj->devctx.VIS_sensor_fps.val = 25;//帧数浮动改用具体数值操作
            freezetime_msg_send(100);
            hal_cs_set_monomode2(1);
            hal_cs_set_awb(2);
            hal_cs_set_adgain(1000, 512000);//最高512倍
            IRCUT_modle(1);
            break;
        case 2: //黄昏模式 25hz 探测器自动调节25hz
            pobj->devctx.VIS_sensor_fps.val = 25;//25
            freezetime_msg_send(200);
            hal_cs_set_monomode2(2);
            hal_cs_set_awb(1);
            hal_cs_set_capmode(1, pobj->devctx.VIS_sensor_fps.val);
            hal_cs_set_shutter(40000, pobj->devctx.VIS_sensor_fps.val);
            hal_cs_set_adgain(1000, 512000);
            IRCUT_modle(1);
            break;
        }
        break;
    case TYPE_FPGA_256X192:
    case TYPE_FPGA_384X288:
    case TYPE_FPGA_640X512:
        pobj->devctx.color_mode.val++;
        if (pobj->devctx.color_mode.val > pobj->devctx.color_mode.max) {
            pobj->devctx.color_mode.val = 0;
        }
        HAL_FPGA_colormode(pobj->devctx.color_mode.val);
        break;
    default:
        pobj->devctx.color_mode.val++;
        if (pobj->devctx.color_mode.val > pobj->devctx.color_mode.max) {
            pobj->devctx.color_mode.val = 0;
        }
        hal_thermal_color_mode(pobj->devctx.color_mode.val);
        break;
    }

    return 0;
}

static int setup_normal_shutter_cal(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    switch (pobj->devctx.sensor_type.val)
    {
    case TYPE_VIS_1920X1080:
        break;
    case TYPE_FPGA_256X192:
    case TYPE_FPGA_384X288:
    case TYPE_FPGA_640X512:
        HAL_FPGA_shutter_cal();
        break;
    default:
        hal_thermal_shutter_cal();
        break;
    }

    return 0;
}

static int setup_normal_bg_cal(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    if (TYPE_VIS_1920X1080 != pobj->devctx.sensor_type.val) {
        // TODO:背景矫正
        pobj->devctx.bg_cal_tick.val = 10;
    }

    return 0;
}

static int setup_normal_entry(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    if (pobj->devctx.reticle.val) {
        hal_cross_update(1, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);
    }
    if (id_image_adjust == pobj->curid) {
        hal_thermal_shutter_cal();
    }
    
    pobj->curid = id_normal;

    return 0;
}

/*
 * Menu 界面
 * 30 秒无任何按键操作：进入 Idle 界面。
 * 上键短按：往上移动一格焦点，能循环调整。
 * 下键短按：往下移动一格焦点，能循环调整。
 * 确认键短按：确认焦点。
 * 确认键长按：不保存选值，退回到 Idle 界面。
 * 其他按键操作，无功能。
 */
static int setup_mainmenu1_choice(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    int index = pobj->devctx.mainmenu1.curnode.val;
    int nid = pobj->devctx.mainmenu1.node[index]->nid;
    switch (nid)
    {
    case nid_menu_image:
        pobj->devctx.status_sel.val = 0;
        pobj->devctx.status_sel.max = 2;    // image adjust、image setting、return
        pobj->curid = id_image;
        break;
    case nid_menu_camera_setting:   // 可见光
        pobj->devctx.status_sel.val = 0;
        pobj->devctx.status_sel.max = nid_camera_setting_return;
        pobj->curid = id_camera_setting;
        break;
    case nid_menu_reticle:
        pobj->devctx.status_sel.val = 0;
        pobj->devctx.status_sel.max = 3;    // reticle enable、cross color、reticle coordinate、return
        pobj->curid = id_reticle;
        break;
    case nid_menu_nine_axis_setting:
        pobj->devctx.status_sel.val = 0;
        pobj->devctx.status_sel.max = pobj->devctx.nine_axis.max + 1;    // gyro、compass、compass cal、return
        pobj->curid = id_nine_axis_setting;
        break;
    case nid_menu_system:
        pobj->devctx.status_sel.val = 0;
        pobj->devctx.status_sel.max = nid_system_return;    // language、factory reset、information、return
        pobj->curid = id_system;
        break;
    case nid_menu_exit:
        if (pobj->devctx.reticle.val) {
            hal_cross_update(1, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);
        }
        pobj->curid = id_normal;
        break;
    }

    return 0;
}

static int setup_mainmenu1_sel_pre(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.mainmenu1.curnode.val--;
    if (pobj->devctx.mainmenu1.curnode.val < 0) {
        pobj->devctx.mainmenu1.curnode.val = pobj->devctx.mainmenu1.curnode.max;
    }

    return 0;
}

static int setup_mainmenu1_sel_next(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.mainmenu1.curnode.val++;
    if (pobj->devctx.mainmenu1.curnode.val > pobj->devctx.mainmenu1.curnode.max) {
        pobj->devctx.mainmenu1.curnode.val = 0;
    }

    return 0;
}

/*
 * 图像界面
 * 30 秒无任何按键：进入 Idle 界面。
 * 上键短按：往上移动一格焦点，能循环调整。
 * 下键短按：往下移动一格焦点，能循环调整。
 * 确认键短按：确认焦点。
 * 确认键长按：不保存选值，退回到 Idle 界面。
 * 其他按键操作，无功能。
 */
static int setup_image_choice(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    switch (pobj->devctx.status_sel.val)
    {
    case 0:
        pobj->devctx.image_adjust.curnode.val = 0;
        pobj->curid = id_image_adjust;
        break;
    case 1:
        pobj->devctx.image_setting.curnode.val = 0;
        pobj->curid = id_image_setting;
        break;
    case 2:
        pobj->curid = id_mainmenu1;
        break;
    }

    return 0;
}

static int setup_sub_menu_sel_pre(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val--;
    if (pobj->devctx.status_sel.val < 0) {
        pobj->devctx.status_sel.val = pobj->devctx.status_sel.max;
    }

    return 0;
}

static int setup_sub_menu_sel_next(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val++;
    if (pobj->devctx.status_sel.val > pobj->devctx.status_sel.max) {
        pobj->devctx.status_sel.val = 0;
    }

    return 0;
}

/*
 * 图像调整界面
 * 30 秒无任何按键：进入 Idle 界面。
 * 上键短按：往上移动一格焦点，能循环调整。
 * 下键短按：往下移动一格焦点，能循环调整。
 * 确认键短按：焦点在返回选项时，返回图像界面。
 *          焦点在其他选项时，无功能。
 * 左键短按：焦点在返回选项时，无功能。
 *          焦点在其他选项时，减小数值，能循环调整。
 * 右键短按：焦点在返回选项时，无功能。
 *          焦点在其他选项时，增大数值，能循环调整。
 * 确认键长按：不保存选值，退回到 Idle 界面。
 * 其他按键操作，无功能。
 */
static int setup_image_adjust_choice(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    
    if (pobj->devctx.image_adjust.curnode.val == pobj->devctx.image_adjust.curnode.max) {
        pobj->curid = id_image;
        hal_thermal_shutter_cal();
    }

    return 0;
}

static int setup_image_adjust_sel_pre(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.image_adjust.curnode.val--;
    if (pobj->devctx.image_adjust.curnode.val < 0) {
        pobj->devctx.image_adjust.curnode.val = pobj->devctx.image_adjust.curnode.max;
    }

    return 0;
}

static int setup_image_adjust_sel_next(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.image_adjust.curnode.val++;
    if (pobj->devctx.image_adjust.curnode.val > pobj->devctx.image_adjust.curnode.max) {
        pobj->devctx.image_adjust.curnode.val = 0;
    }

    return 0;
}

static int setup_image_adjust_dec(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    if (pobj->devctx.image_adjust.curnode.val != pobj->devctx.image_adjust.curnode.max) {
        pobj->devctx.save_para_tick.val = 25;
        int index = pobj->devctx.image_adjust.curnode.val;

        pobj->devctx.image_adjust.node[index]->val--;
        if (pobj->devctx.image_adjust.node[index]->val < 0) {
            pobj->devctx.image_adjust.node[index]->val = pobj->devctx.image_adjust.node[index]->max;
        }
        switch (pobj->devctx.image_adjust.node[index]->nid)
        {
        case nid_image_adjust_brightness:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                hal_cs_set_brightness(pobj->devctx.image_adjust.node[index]->val * 20);
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_brightness(pobj->devctx.image_adjust.node[index]->val);
                break;
            default:
                hal_thermal_set_bright(pobj->devctx.image_adjust.node[index]->val);
                break;
            }
            break;
        case nid_image_adjust_contrast:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                hal_cs_set_contrast(pobj->devctx.image_adjust.node[index]->val * 20);
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_contrast(pobj->devctx.image_adjust.node[index]->val);
                break;
            default:
                hal_thermal_set_contrast(pobj->devctx.image_adjust.node[index]->val);
                break;
            }
            break;
        // case nid_image_adjust_detail_enhance:
        //     if (TYPE_VIS_1920X1080 == pobj->devctx.sensor_type.val) {

        //     } else {
        //         hal_thermal_set_sharpness(pobj->devctx.image_adjust.node[index]->val);
        //     }
        //     break;
        case nid_image_adjust_sharpness:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                hal_cs_set_sharpness(pobj->devctx.image_adjust.node[index]->val * 40);
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_detail_enhance(pobj->devctx.image_adjust.node[index]->val);
                break;
            default:
                hal_thermal_set_sharpness(pobj->devctx.image_adjust.node[index]->val);
                break;
            }
            break;
        // case nid_image_adjust_gamma:
        //     if (TYPE_VIS_1920X1080 == pobj->devctx.sensor_type.val) {

        //     } else {
        //         hal_thermal_set_gamma(pobj->devctx.image_adjust.node[index]->val);
        //     }
        //     break;
        case nid_image_adjust_img_3D_denoise:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                hal_cs_set_3Ddenoiselevel(pobj->devctx.image_adjust.node[index]->val * 40);
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_time_domain_denoise(pobj->devctx.image_adjust.node[index]->val);
                break;
            default:
                hal_thermal_set_3Ddenoiselevel(pobj->devctx.image_adjust.node[index]->val);
                break;
            }
            break;
        case nid_image_adjust_img_2D_denoise:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                hal_cs_set_2Ddenoiselevel(pobj->devctx.image_adjust.node[index]->val * 40);
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_Space_domain_denoise(pobj->devctx.image_adjust.node[index]->val);
                break;
            default:
                hal_thermal_set_2Ddenoiselevel(pobj->devctx.image_adjust.node[index]->val);
                break;
            }
            break;
        }
    }

    return 0;
}

static int setup_image_adjust_inc(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    if (pobj->devctx.image_adjust.curnode.val != pobj->devctx.image_adjust.curnode.max) {
        pobj->devctx.save_para_tick.val = 25;
        int index = pobj->devctx.image_adjust.curnode.val;

        pobj->devctx.image_adjust.node[index]->val++;
        if (pobj->devctx.image_adjust.node[index]->val > pobj->devctx.image_adjust.node[index]->max) {
            pobj->devctx.image_adjust.node[index]->val = 0;
        }
        switch (pobj->devctx.image_adjust.node[index]->nid)
        {
        case nid_image_adjust_brightness:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                hal_cs_set_brightness(pobj->devctx.image_adjust.node[index]->val * 20);
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_brightness(pobj->devctx.image_adjust.node[index]->val);
                break;
            default:
                hal_thermal_set_bright(pobj->devctx.image_adjust.node[index]->val);
                break;
            }
            break;
        case nid_image_adjust_contrast:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                hal_cs_set_contrast(pobj->devctx.image_adjust.node[index]->val * 20);
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_contrast(pobj->devctx.image_adjust.node[index]->val);
                break;
            default:
                hal_thermal_set_contrast(pobj->devctx.image_adjust.node[index]->val);
                break;
            }
            break;
        // case nid_image_adjust_detail_enhance:
        //     if (TYPE_VIS_1920X1080 == pobj->devctx.sensor_type.val) {

        //     } else {
        //         hal_thermal_set_sharpness(pobj->devctx.image_adjust.node[index]->val);
        //     }
        //     break;
        case nid_image_adjust_sharpness:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                hal_cs_set_sharpness(pobj->devctx.image_adjust.node[index]->val * 40);
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_detail_enhance(pobj->devctx.image_adjust.node[index]->val);
                break;
            default:
                hal_thermal_set_sharpness(pobj->devctx.image_adjust.node[index]->val);
                break;
            }
            break;
        // case nid_image_adjust_gamma:
        //     if (TYPE_VIS_1920X1080 == pobj->devctx.sensor_type.val) {

        //     } else {
        //         hal_thermal_set_gamma(pobj->devctx.image_adjust.node[index]->val);
        //     }
        //     break;
        case nid_image_adjust_img_3D_denoise:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                hal_cs_set_3Ddenoiselevel(pobj->devctx.image_adjust.node[index]->val * 40);
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_time_domain_denoise(pobj->devctx.image_adjust.node[index]->val);
                break;
            default:
                hal_thermal_set_3Ddenoiselevel(pobj->devctx.image_adjust.node[index]->val);
                break;
            }
            break;
        case nid_image_adjust_img_2D_denoise:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                hal_cs_set_2Ddenoiselevel(pobj->devctx.image_adjust.node[index]->val * 40);
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_Space_domain_denoise(pobj->devctx.image_adjust.node[index]->val);
                break;
            default:
                hal_thermal_set_2Ddenoiselevel(pobj->devctx.image_adjust.node[index]->val);
                break;
            }
            break;
        }
    }

    return 0;
}

/*
 * 图像设置界面
 * 30 秒无任何按键：进入 Idle 界面。
 * 上键短按：往上移动一格焦点，能循环调整。
 * 下键短按：往下移动一格焦点，能循环调整。
 * 确认键短按：焦点在返回选项时，返回图像界面。
 *          焦点在其他选项时，无功能。
 * 左键短按：焦点在返回选项时，无功能。
 *          焦点在其他选项时，减小数值，能循环调整。
 * 右键短按：焦点在返回选项时，无功能。
 *          焦点在其他选项时，增大数值，能循环调整。
 * 确认键长按：不保存选值，退回到 Idle 界面。
 * 其他按键操作，无功能。
 */
static int setup_image_setting_choice(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    
    if (nid_image_setting_return == pobj->devctx.image_setting.curnode.val) {
        pobj->curid = id_image;
    }

    return 0;
}

static int setup_image_setting_sel_pre(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.image_setting.curnode.val--;
    if (pobj->devctx.image_setting.curnode.val < 0) {
        pobj->devctx.image_setting.curnode.val = pobj->devctx.image_setting.curnode.max;
    }

    return 0;
}

static int setup_image_setting_sel_next(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.image_setting.curnode.val++;
    if (pobj->devctx.image_setting.curnode.val > pobj->devctx.image_setting.curnode.max) {
        pobj->devctx.image_setting.curnode.val = 0;
    }

    return 0;
}

static int setup_image_setting_dec(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    int index = pobj->devctx.image_setting.curnode.val;
    if (nid_image_setting_return != index) {
        pobj->devctx.image_setting.node[index]->val--;
        if (pobj->devctx.image_setting.node[index]->val < 0) {
            pobj->devctx.image_setting.node[index]->val = pobj->devctx.image_setting.node[index]->max;
        }
        switch (pobj->devctx.image_setting.node[index]->nid)
        {
        case nid_image_setting_mirror:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                /* code */
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_mirror(pobj->devctx.image_setting.node[index]->val);
                break;
            default:
                hal_thermal_mirror(pobj->devctx.image_setting.node[index]->val);
                break;
            }
            break;
        case nid_image_setting_flip:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                /* code */
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_flip(pobj->devctx.image_setting.node[index]->val);
                break;
            default:
                hal_thermal_flip(pobj->devctx.image_setting.node[index]->val);
                break;
            }
            break;
        case nid_image_setting_EIS:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                /* code */
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                /* code */
                break;
            default:
                hal_thermal_eis(pobj->devctx.image_setting.node[index]->val, 0, 0, 0);
                break;
            }
            break;
        }
        pobj->devctx.save_para_tick.val = 25;
    }

    return 0;
}

static int setup_image_setting_inc(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    int index = pobj->devctx.image_setting.curnode.val;
    if (nid_image_setting_return != index) {
        pobj->devctx.image_setting.node[index]->val++;
        if (pobj->devctx.image_setting.node[index]->val > pobj->devctx.image_setting.node[index]->max) {
            pobj->devctx.image_setting.node[index]->val = 0;
        }
        switch (pobj->devctx.image_setting.node[index]->nid)
        {
        case nid_image_setting_mirror:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                /* code */
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_mirror(pobj->devctx.image_setting.node[index]->val);
                break;
            default:
                hal_thermal_mirror(pobj->devctx.image_setting.node[index]->val);
                break;
            }
            break;
        case nid_image_setting_flip:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                /* code */
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                HAL_FPGA_flip(pobj->devctx.image_setting.node[index]->val);
                break;
            default:
                hal_thermal_flip(pobj->devctx.image_setting.node[index]->val);
                break;
            }
            break;
        case nid_image_setting_EIS:
            switch (pobj->devctx.sensor_type.val)
            {
            case TYPE_VIS_1920X1080:
                /* code */
                break;
            case TYPE_FPGA_256X192:
            case TYPE_FPGA_384X288:
            case TYPE_FPGA_640X512:
                /* code */
                break;
            default:
                hal_thermal_eis(pobj->devctx.image_setting.node[index]->val, 0, 0, 0);
                break;
            }
            break;
        }
        pobj->devctx.save_para_tick.val = 25;
    }

    return 0;
}

/*
 * 微光夜视镜头：
 * 30 秒无任何按键：进入 Idle 界面。
 * 上键短按：往上切换焦点，能循环调整。
 * 下键短按：往下切换焦点，能循环调整。
 * 左键短按：当焦点在返回选项，白平衡设置选项时，无功能。
 *          当焦点在其他选项时，往左切换选值，可循环切换。
 * 右键短按：当焦点在返回选项，白平衡设置选项时，无功能。
 *          当焦点在其他选项时，往右切换选值，可循环切换。
 * 确认键短按：当焦点在返回选项时，确认焦点。
 *          当焦点在白平衡设置选项时，进入白平衡设置界面。
 *          当焦点在其他选项时，无功能。
 * 确认键长按：不保存选值，退回到 Idle 界面。
 * 其他按键操作，无功能。
 */
static int setup_camera_setting_choice(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    
    switch (pobj->devctx.status_sel.val)
    {
    case nid_camera_setting_WB:
        pobj->devctx.status_sel.val = 0;
        pobj->devctx.status_sel.max = 2;    // 0：白平衡设置，1：色温，2：return
        pobj->curid = id_WB_setting;
        break;
    case nid_camera_setting_return:
        pobj->curid = id_mainmenu1;
        break;
    }

    return 0;
}

static int setup_camera_setting_dec(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.save_para_tick.val = 25;
    switch (pobj->devctx.status_sel.val)
    {
    case nid_camera_setting_VIS_mode:
        pobj->devctx.VIS_mode.val--;
        if (pobj->devctx.VIS_mode.val < 0) {
            pobj->devctx.VIS_mode.val = pobj->devctx.VIS_mode.max;
        }
        // TODO:可见光模式切换
        switch (pobj->devctx.VIS_mode.val)
        {
        case 0: // 白天模式 50hz 探测器自动调节50hz
            if(pobj->devctx.rec.val > 0) {
                pobj->devctx.VIS_sensor_fps.val = 25;
            } else {
                pobj->devctx.VIS_sensor_fps.val = 50;
            }
            freezetime_msg_send(125);//冻结时间按照星光帧率计算
            hal_cs_set_monomode2(0);
            hal_cs_set_awb(0);
            hal_cs_set_capmode(1, pobj->devctx.VIS_sensor_fps.val);   
            hal_cs_set_shutter(40000, pobj->devctx.VIS_sensor_fps.val);
            hal_cs_set_adgain(1000, 384000);
            IRCUT_modle(0);
            break;
        case 1: //星光模式 25hz 探测器自动调节12hz
            pobj->devctx.VIS_sensor_fps.val = 25;//帧数浮动改用具体数值操作
            freezetime_msg_send(100);
            hal_cs_set_monomode2(1);
            hal_cs_set_awb(2);
            hal_cs_set_adgain(1000, 512000);//最高512倍
            IRCUT_modle(1);
            break;
        case 2: //黄昏模式 25hz 探测器自动调节25hz
            pobj->devctx.VIS_sensor_fps.val = 25;//25
            freezetime_msg_send(200);
            hal_cs_set_monomode2(2);
            hal_cs_set_awb(1);
            hal_cs_set_capmode(1, pobj->devctx.VIS_sensor_fps.val);
            hal_cs_set_shutter(40000, pobj->devctx.VIS_sensor_fps.val);
            hal_cs_set_adgain(1000, 512000);
            IRCUT_modle(1);
            break;
        }
        break;
    case nid_camera_setting_EC:
        pobj->devctx.EC.val--;
        if (pobj->devctx.EC.val < 0) {
            pobj->devctx.EC.val = pobj->devctx.EC.max;
        }
        // TODO:曝光补偿
        hal_cs_set_ev(25 + pobj->devctx.EC.val * 31);
        break;
    case nid_camera_setting_WDR:
        pobj->devctx.WDR.val--;
        if (pobj->devctx.WDR.val < 0) {
            pobj->devctx.WDR.val = pobj->devctx.WDR.max;
        }
        // TODO:宽动态设置
        break;
    }

    return 0;
}

static int setup_camera_setting_inc(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.save_para_tick.val = 25;
    switch (pobj->devctx.status_sel.val)
    {
    case nid_camera_setting_VIS_mode:
        pobj->devctx.VIS_mode.val++;
        if (pobj->devctx.VIS_mode.val > pobj->devctx.VIS_mode.max) {
            pobj->devctx.VIS_mode.val = 0;
        }
        switch (pobj->devctx.VIS_mode.val)
        {
        case 0: // 白天模式 50hz 探测器自动调节50hz
            if(pobj->devctx.rec.val > 0) {
                pobj->devctx.VIS_sensor_fps.val = 25;
            } else {
                pobj->devctx.VIS_sensor_fps.val = 50;
            }
            freezetime_msg_send(125);//冻结时间按照星光帧率计算
            hal_cs_set_monomode2(0);
            hal_cs_set_awb(0);
            hal_cs_set_capmode(1, pobj->devctx.VIS_sensor_fps.val);   
            hal_cs_set_shutter(40000, pobj->devctx.VIS_sensor_fps.val);
            hal_cs_set_adgain(1000, 384000);
            IRCUT_modle(0);
            break;
        case 1: //星光模式 25hz 探测器自动调节12hz
            pobj->devctx.VIS_sensor_fps.val = 25;//帧数浮动改用具体数值操作
            freezetime_msg_send(100);
            hal_cs_set_monomode2(1);
            hal_cs_set_awb(2);
            hal_cs_set_adgain(1000, 512000);//最高512倍
            IRCUT_modle(1);
            break;
        case 2: //黄昏模式 25hz 探测器自动调节25hz
            pobj->devctx.VIS_sensor_fps.val = 25;//25
            freezetime_msg_send(200);
            hal_cs_set_monomode2(2);
            hal_cs_set_awb(1);
            hal_cs_set_capmode(1, pobj->devctx.VIS_sensor_fps.val);
            hal_cs_set_shutter(40000, pobj->devctx.VIS_sensor_fps.val);
            hal_cs_set_adgain(1000, 512000);
            IRCUT_modle(1);
            break;
        }
        break;
    case nid_camera_setting_EC:
        pobj->devctx.EC.val++;
        if (pobj->devctx.EC.val > pobj->devctx.EC.max) {
            pobj->devctx.EC.val = 0;
        }
        hal_cs_set_ev(25 + pobj->devctx.EC.val * 31);
        break;
    case nid_camera_setting_WDR:
        pobj->devctx.WDR.val++;
        if (pobj->devctx.WDR.val > pobj->devctx.WDR.max) {
            pobj->devctx.WDR.val = 0;
        }
        break;
    }

    return 0;
}

/*
 * 白平衡设置界面
 * 30 秒无任何按键：进入 Idle 界面。
 * 上键短按：往上切换焦点，能循环调整。
 * 下键短按：往下切换焦点，能循环调整。
 * 左键短按：焦点在返回选项时，无功能。
 *          焦点在其他选项时，往左切换选值，能循环调整。
 * 右键短按：焦点在返回选项时，无功能。
 *          焦点在其他选项时，往右切换选值，能循环调整。
 * 确认键短按：焦点在返回选项时，返回 Camera Setting 界面。
 *          焦点在其他选项时，无功能。
 * 确认键长按：不保存选值，退回到 Idle 界面。
 * 其他按键操作，无功能。
 */
static int setup_WB_setting_choice(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    
    if (pobj->devctx.status_sel.val == pobj->devctx.status_sel.max) {
        pobj->devctx.status_sel.val = nid_camera_setting_WB;
        pobj->devctx.status_sel.max = nid_camera_setting_return;
        pobj->curid = id_camera_setting;
    }

    return 0;
}

static int setup_WB_setting_sel_pre(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val--;
    if (0 == pobj->devctx.WB_mode.val && 1 == pobj->devctx.status_sel.val) {
        pobj->devctx.status_sel.val--;
    }
    if (pobj->devctx.status_sel.val < 0) {
        pobj->devctx.status_sel.val = pobj->devctx.status_sel.max;
    }

    return 0;
}

static int setup_WB_setting_sel_next(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val++;
    if (0 == pobj->devctx.WB_mode.val && 1 == pobj->devctx.status_sel.val) {
        pobj->devctx.status_sel.val++;
    }
    if (pobj->devctx.status_sel.val > pobj->devctx.status_sel.max) {
        pobj->devctx.status_sel.val = 0;
    }

    return 0;
}

static int setup_WB_setting_dec(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.save_para_tick.val = 25;
    switch (pobj->devctx.status_sel.val)
    {
    case 0:
        pobj->devctx.WB_mode.val = 1 - pobj->devctx.WB_mode.val;
        break;
    case 1:
        pobj->devctx.color_temp.val--;
        if (pobj->devctx.color_temp.val < 0) {
            pobj->devctx.color_temp.val = pobj->devctx.color_temp.max;
        }
        switch (pobj->devctx.color_temp.val)
        {
        case 0:
            hal_cs_set_hue(-90);
            break;
        case 1:
            hal_cs_set_hue(90);
            break;
        case 2:
            hal_cs_set_hue(360);
            break;
        }
        
        break;
    }

    return 0;
}

static int setup_WB_setting_inc(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.save_para_tick.val = 25;
    switch (pobj->devctx.status_sel.val)
    {
    case 0:
        pobj->devctx.WB_mode.val = 1 - pobj->devctx.WB_mode.val;
        break;
    case 1:
        pobj->devctx.color_temp.val++;
        if (pobj->devctx.color_temp.val > pobj->devctx.color_temp.max) {
            pobj->devctx.color_temp.val = 0;
        }
        switch (pobj->devctx.color_temp.val)
        {
        case 0:
            hal_cs_set_hue(-90);
            break;
        case 1:
            hal_cs_set_hue(90);
            break;
        case 2:
            hal_cs_set_hue(360);
            break;
        }
        break;
    }

    return 0;
}
/*
 * 十字分化选择界面
 * 30 秒无任何按键：进入 Idle 界面。
 * 上键短按：往上切换焦点，能循环调整。
 * 下键短按：往下切换焦点，能循环调整。
 * 确认键短按：当焦点在十字分化选项时，无功能。
 * 当焦点在十字分化坐标选项时，确认焦点。
 * 当焦点在返回选项时，确认焦点。
 * 左键短按：当焦点在十字分化选项时，往左切换选值，能循环调整。
 *          当焦点在其他选项时，无功能。
 * 右键短按：当焦点在十字分化选项时，往右切换选值，能循环调整。
 *          当焦点在其他选项时，无功能。
 * 确认键长按：不保存选值，退回到 Idle 界面。
 * 其他按键操作，无功能。
 */
static int setup_reticle_choice(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    
    switch (pobj->devctx.status_sel.val)
    {
    case 1: // cross_color
        hal_cross_update(1, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);
        pobj->devctx.status_sel.val = pobj->devctx.cross_color.val;
        pobj->devctx.status_sel.max = 4;
        pobj->curid = id_cross_color_setting;
        break;
    case 2: // gun_cal
        hal_cross_update(1, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);
        pobj->curid = id_gun_cal;
        break;
    case 3: // return
        pobj->curid = id_mainmenu1;
        break;
    }

    return 0;
}

static int setup_reticle_sel_pre(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val--;
    if (!pobj->devctx.reticle.val && pobj->devctx.status_sel.val == pobj->devctx.status_sel.max - 1) {
        pobj->devctx.status_sel.val -= 2;
    }
    if (pobj->devctx.status_sel.val < 0) {
        pobj->devctx.status_sel.val = pobj->devctx.status_sel.max;
    }

    return 0;
}

static int setup_reticle_sel_next(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val++;
    if (!pobj->devctx.reticle.val && 1 == pobj->devctx.status_sel.val) {
        pobj->devctx.status_sel.val += 2;
    }
    if (pobj->devctx.status_sel.val > pobj->devctx.status_sel.max) {
        pobj->devctx.status_sel.val = 0;
    }

    return 0;
}

static int setup_reticle_switch(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    if (0 == pobj->devctx.status_sel.val) {
        pobj->devctx.save_para_tick.val = 25;
        pobj->devctx.reticle.val = 1 - pobj->devctx.reticle.val;
    }

    return 0;
}

/*
 * 十字分化颜色设置界面
 * 30 秒无任何按键：进入 Idle 界面。
 * 上键短按：往上切换焦点，能循环调整。
 * 下键短按：往下切换焦点，能循环调整。
 * 确认键短按：确认焦点。
 * 确认键长按：不保存选值，退回到 Idle 界面。
 * 其他按键操作，无功能。
 */
static int setup_cross_color_setting_choice(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    if (pobj->devctx.status_sel.val != pobj->devctx.status_sel.max) {
        pobj->devctx.save_para_tick.val = 25;
        pobj->devctx.cross_color.val = pobj->devctx.status_sel.val;
    }
    pobj->devctx.status_sel.val = 1;
    pobj->devctx.status_sel.max = 3;
    hal_cross_update(0, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);
    pobj->curid = id_reticle;

    return 0;
}

static int setup_cross_color_setting_pre(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val--;
    if (pobj->devctx.status_sel.val < 0) {
        pobj->devctx.status_sel.val = pobj->devctx.status_sel.max;
    }
    if (pobj->devctx.status_sel.val != pobj->devctx.status_sel.max) {
        hal_cross_update(1, pobj->devctx.cross_type.val, pobj->devctx.status_sel.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);
    }

    return 0;
}

static int setup_cross_color_setting_next(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val++;
    if (pobj->devctx.status_sel.val > pobj->devctx.status_sel.max) {
        pobj->devctx.status_sel.val = 0;
    }
    if (pobj->devctx.status_sel.val != pobj->devctx.status_sel.max) {
        hal_cross_update(1, pobj->devctx.cross_type.val, pobj->devctx.status_sel.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);
    }

    return 0;
}

/*
 * 30 秒无任何按键：进入 Idle 界面。
 * 左键短按：X 轴坐标中心点往左移动，步进一个像素点。
 * 左键长按：X 轴坐标中心点连续往左移动。
 * 右键短按：X 轴坐标中心点往右移动，步进一个像素点。
 * 右键长按：X 轴坐标中心点连续往右移动。
 * 上键短按：Y 轴坐标中心点往上移动，步进一个像素点。
 * 上键长按：Y 轴坐标中心点连续往上移动。
 * 下键短按：Y 轴坐标中心点往下移动，步进一个像素点。
 * 下键长按：Y 轴坐标中心点连续往下移动。
 * 确认键长按：保存调整的值，返回十字分化选择界面。
 * 其他按键操作，无功能。
 */
static int setup_gun_cal_save(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.save_para_tick.val = 25;
    hal_save_para(PARA_CROSS_POS_X, pobj->devctx.cross_pos.center_x.val);
    hal_save_para(PARA_CROSS_POS_Y, pobj->devctx.cross_pos.center_y.val);
    hal_cross_update(0, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);
    pobj->curid = id_reticle;
    
    return 0;
}

static int setup_gun_cal_up(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.cross_pos.center_y.val--;
    if (pobj->devctx.cross_pos.center_y.val < pobj->devctx.cross_pos.center_y.min) {
        pobj->devctx.cross_pos.center_y.val = pobj->devctx.cross_pos.center_y.min;
    }
    hal_cross_update(1, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);

    return 0;
}

static int setup_gun_cal_down(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.cross_pos.center_y.val++;
    if (pobj->devctx.cross_pos.center_y.val > pobj->devctx.cross_pos.center_y.max) {
        pobj->devctx.cross_pos.center_y.val = pobj->devctx.cross_pos.center_y.max;
    }
    hal_cross_update(1, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);

    return 0;
}

static int setup_gun_cal_left(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.cross_pos.center_x.val--;
    if (pobj->devctx.cross_pos.center_x.val < pobj->devctx.cross_pos.center_x.min) {
        pobj->devctx.cross_pos.center_x.val = pobj->devctx.cross_pos.center_x.min;
    }
    hal_cross_update(1, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);

    return 0;
}

static int setup_gun_cal_right(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.cross_pos.center_x.val++;
    if (pobj->devctx.cross_pos.center_x.val > pobj->devctx.cross_pos.center_x.max) {
        pobj->devctx.cross_pos.center_x.val = pobj->devctx.cross_pos.center_x.max;
    }
    hal_cross_update(1, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);

    return 0;
}

/*
 * 系统设置调整界面
 * 30 秒无任何按键：进入 Idle 界面。
 * 上键短按：往上切换焦点，能循环调整。
 * 下键短按：往下切换焦点，能循环调整。
 * 确认键短按：确认焦点。
 * 其他按键操作，无功能。
 */
static Uint32 compass_correct_timer_callback(Uint32 interval, void *param)
{
    UICtx_t *pobj = (UICtx_t*)param;

    Hal_ICM20948_calibration(&pobj->devctx.compass_cal.val);
    pobj->devctx.status_sel.val = 2;
    pobj->devctx.status_sel.max = pobj->devctx.nine_axis.max + 1;
    pobj->curid = id_nine_axis_setting;

    return 0;
}

int setup_compass_cal_entry(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.compass.val = 0;
    pobj->devctx.compass_cal.val = 1;

    SDL_RemoveTimer(SDL_timer_id);
    SDL_timer_id = SDL_AddTimer(200, compass_correct_timer_callback, pobj);

    return 0;
}

/*
 * 九轴设置界面
 * 30 秒无任何按键：进入 Idle 界面。
 * 上键短按：往上切换焦点，能循环调整。
 * 下键短按：往下切换焦点，能循环调整。
 * 确认键短按：当焦点在陀螺仪和电子罗盘选项时，无功能。
 * 当焦点在电子罗盘校准选项时，确认焦点。
 * 当焦点在返回选项时，确认焦点。
 * 左键短按：当焦点在陀螺仪和电子罗盘选项时，往左切换选值，能循环调整。
 * 当焦点在其他选项时，无功能。
 * 右键短按：当焦点在陀螺仪和电子罗盘选项时，往右切换选值，能循环调整。
 * 当焦点在其他选项时，无功能。
 * 确认键长按：不保存选值，退回到 Idle 界面。
 * 其他按键操作，无功能。
 */
static int setup_nine_axis_choice(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    
    switch (pobj->devctx.status_sel.val)
    {
    case 2:
        pobj->curid = id_compass_cal;
        setup_compass_cal_entry(pobj);
        break;
    case 3:
        pobj->curid = id_mainmenu1;
        break;
    }

    return 0;
}

static int setup_nine_axis_switch(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    switch (pobj->devctx.status_sel.val)
    {
    case 0:
        pobj->devctx.motion.val = 1 - pobj->devctx.motion.val;
        pobj->devctx.save_para_tick.val = 25;
        break;
    case 1:
        pobj->devctx.compass.val = 1 - pobj->devctx.compass.val;
        pobj->devctx.save_para_tick.val = 25;
        break;
    }

    return 0;
}

static int setup_ver_info_entry(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    if (!pobj->sys_info.sn[0]) {
        load_oeminfo_from_flash("OEM_SERIL_NUM", pobj->sys_info.sn, 16);
        read_rootfs_version(pobj->sys_info.sys_ver, 32);
        memcpy(pobj->sys_info.gui_ver, GUI_VERSION, sizeof(GUI_VERSION));
    }

    return 0;
}

static int setup_system_choice(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    
    switch (pobj->devctx.status_sel.val)
    {
    case nid_system_langua:
        pobj->curid = id_language;
        pobj->devctx.status_sel.val = 0;
        pobj->devctx.status_sel.max = 2;
        break;
    case nid_system_factory_reset:
        pobj->curid = id_factory_reset;
        pobj->devctx.status_sel.val = 0;
        pobj->devctx.status_sel.max = 1;
        pobj->devctx.menu_entry.val = 0;
        break;
    case nid_system_ver_info:
        pobj->curid = id_ver_info;
        setup_ver_info_entry(pso);
        break;
    case nid_system_return:
        pobj->curid = id_mainmenu1;
        break;
    }

    return 0;
}

/*
 * 语言设置界面
 * 30 秒无任何按键：进入 Idle 界面。
 * 上键短按：往上切换焦点，能循环调整。
 * 下键短按：往下切换焦点，能循环调整。
 * 确认键短按：确认焦点。
 * 确认键长按：不保存选值，退回到 Idle 界面。
 * 其他按键操作，无功能。
 */
static int setup_language_choice(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    
    if (pobj->devctx.status_sel.val != pobj->devctx.status_sel.max) {
        pobj->devctx.save_para_tick.val = 25;
        pobj->devctx.language.val = pobj->devctx.status_sel.val;
    }
    pobj->curid = id_system;
    pobj->devctx.status_sel.val = nid_system_langua;
    pobj->devctx.status_sel.max = nid_system_return;    // language、factory reset、information、return

    return 0;
}

static int setup_compass_cal_exit(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.compass_cal.val = 0;

    return 0;
}

/*
 * 恢复出厂设置界面
 * 30 秒无任何按键：进入 Idle 界面。
 * 上键短按：往上切换焦点，能循环调整。
 * 下键短按：往下切换焦点，能循环调整。
 * 确认键短按：确认焦点。
 * 确认键长按：不保存选值，退回到 Idle 界面。
 * 其他按键操作，无功能。
 */
static int setup_factory_reset_choice(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    if (pobj->devctx.menu_entry.val) {  // 恢复出厂设置二次确认界面
        if (0 == pobj->devctx.status_sel.val) {
            pobj->curid = id_system;
            pobj->devctx.status_sel.val = nid_system_factory_reset;
            pobj->devctx.status_sel.max = nid_system_return;    // language、factory reset、information、return
        } else {
            // TODO:机芯恢复出厂设置
            save_all_parameters(1, pobj);
            HAL_FPGA_para_recover();
            pobj->devctx.factory_reset.val = 15;
        }
    } else {    // 恢复出厂设置界面
        if (0 == pobj->devctx.status_sel.val) {
            pobj->curid = id_system;
            pobj->devctx.status_sel.val = nid_system_factory_reset;
            pobj->devctx.status_sel.max = nid_system_return;    // language、factory reset、information、return
        } else {
            pobj->devctx.menu_entry.val = 1;
            pobj->devctx.status_sel.val = 0;
        }
    }

    return 0;
}

static int setup_factory_reset_sel_pre(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val = 1 - pobj->devctx.status_sel.val;

    return 0;
}

static int setup_factory_reset_sel_next(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val = 1 - pobj->devctx.status_sel.val;

    return 0;
}

/*
 * 版本信息界面
 * 确认键短按：返回系统界面。
 * 确认键长按：不保存选值，退回到 Idle 界面。
 * 其他按键操作，无功能。
 */
static int setup_ver_info_exit(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val = nid_system_ver_info;
    pobj->devctx.status_sel.max = nid_system_return;    // language、factory reset、information、return
    pobj->curid = id_system;

    return 0;
}

int engineering_key_up_times;
static int setup_engineering_enter(void *pso)
{
	UICtx_t *pobj = (UICtx_t*)pso;

    if (TYPE_SENSOR_384X288 == pobj->devctx.sensor_type.val || TYPE_SENSOR_256X192 == pobj->devctx.sensor_type.val || TYPE_SENSOR_640X512 == pobj->devctx.sensor_type.val) {
        if (++engineering_key_up_times == 5) {
            engineering_key_up_times = 0;
            pobj->curid = id_engineering;
            pobj->devctx.status_sel.val = 0;
            memset(pobj->devctx.cal_status, 0, sizeof(pobj->devctx.cal_status));
            hal_thermal_auto_shutter_onoff(0);
        }
    }

    return 0;
}

static int setup_engineering_exit(void *pso)
{
	UICtx_t *pobj = (UICtx_t*)pso;

    if (++engineering_key_up_times == 5) {
        pobj->curid = id_ver_info;
        engineering_key_up_times = 0;
        hal_thermal_auto_shutter_onoff(1);
    }

    return 0;
}

static int setup_engineering_sel_pre(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val = 1 - pobj->devctx.status_sel.val;

    return 0;
}

static int setup_engineering_sel_next(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;

    pobj->devctx.status_sel.val = 1 - pobj->devctx.status_sel.val;

    return 0;
}

/*
 * # /mnt/default/thermal_msg_sender --calibration 10
 * [MemMgr][Info]: Start to use memory manager library version 4.2.0.0 !!
 * [MemMgr][Info]: Open EDMC device driver version 6.3.0.2 successful !!
 * msg thermal calibration ok
 *
 * # /mnt/default/thermal_msg_sender --calibration 50
 * [MemMgr][Info]: Start to use memory manager library version 4.2.0.0 !!
 * [MemMgr][Info]: Open EDMC device driver version 6.3.0.2 successful !!
 * msg thermal calibration ok
 * 
 * # /mnt/default/thermal_cali1 -c /tmp/config.ini -o /mnt/mtd --bt1data=/tmp/RAW_14BIT_384x288_TMP10.raw --bt2data=/tmp/RAW_14BIT_384x288_TMP50.raw
 * [MemMgr][Info]: Start to use memory manager library version 4.2.0.0 !!
 * [MemMgr][Info]: Open EDMC device driver version 6.3.0.2 successful !!
 * [godshand_read] [Register address : 0xb3f00014] [Value: 0x1000000]
 * [MemMgr][Info]: Start to use memory manager library version 4.2.0.0 !!
 * [MemMgr][Info]: Open EDMC device driver version 6.3.0.2 successful !!
 * Start to use data crypto library version 2.5.0.3 !!
 * [MemMgr][Info]: Start to use memory manager library version 4.2.0.0 !!
 * [MemMgr][Info]: Open EDMC device driver version 6.3.0.2 successful !!
 * Open vma_dce device driver version 2.0.0.4 successful !!
 * [TSP][ERR]: Too many defect pixels. Please check the raw pattern.
 * [TSP][ERR]: Fail to defect pixel detection.
 * [Thermal_Calibration][VMF_TCLI_Calibration] Calibration failed.
 * [main] Calibration failed 
 */
static int setup_engineering_get_para(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    int i;

    if (!pobj->devctx.status_sel.val) {
        /* NUC采集均匀面图像 */
        if (1 != pobj->devctx.cal_status[1].val) {
            system("echo calibration,pocc > /tmp/daemon_in");
            for (i = 0; i < 5; i++) {
                sleep(3);
                if (access("/tmp/RAW_14BIT_NORMAL.raw", F_OK) != -1) {
                    pobj->devctx.cal_status[1].val = 1;
                    break;
                }
            }
            if (5 == i) {
                pobj->devctx.cal_status[1].val = 2;
            }
        }
    } else {
        /* 两点矫正 */
        if (1 != pobj->devctx.cal_status[4].val) { /* 10度 */
            system("echo calibration,low > /tmp/daemon_in");
            sleep(3);
            if (access("/tmp/RAW_14BIT_LOW.raw", F_OK) != -1) {
                pobj->devctx.cal_status[4].val = 1;
            } else {
                pobj->devctx.cal_status[4].val = 2;
            }
        } else if (1 == pobj->devctx.cal_status[4].val && (1 != pobj->devctx.cal_status[5].val)) { /* 50度 */
            system("echo calibration,high > /tmp/daemon_in");
            sleep(3);
            if (access("/tmp/RAW_14BIT_HIGH.raw", F_OK) != -1) {
                pobj->devctx.cal_status[5].val = 1;
            } else {
                pobj->devctx.cal_status[5].val = 2;
            }
        }
    }

    return 0;
}

static int setup_engineering_save_para(void *pso)
{
    UICtx_t *pobj = (UICtx_t*)pso;
    char result[1024] = {0};

    if(!pobj->devctx.status_sel.val) {
        if (1 == pobj->devctx.cal_status[1].val && (1 != pobj->devctx.cal_status[2].val)) {
            // /* NUC矫正参数保存 */
            // struct stat file_stat;
            // time_t prev_mtime; // 之前的修改时间
            // time_t current_mtime; // 当前的修改时间
            // // 获取文件状态信息
            // if (stat("/mnt/mtd/RAW_14BIT_NORMAL.raw", &file_stat) == -1) {
            //     perror("stat");
            // }
            // // 获取之前的修改时间
            // prev_mtime = file_stat.st_mtime;

            /* 均匀面矫正参数保存 */
            execute_command("/mnt/default/thermal_cali0 -c /tmp/config.ini -0 /mnt/mtd", result);
            
            // // 再次获取文件状态信息
            // if (stat("/mnt/mtd/RAW_14BIT_NORMAL.raw", &file_stat) == -1) {
            //     perror("stat");
            // }
            // // 获取当前的修改时间
            // current_mtime = file_stat.st_mtime;
            if (strstr(result, "calibration ok")) {// && prev_mtime != current_mtime) {
                pobj->devctx.cal_status[2].val = 1;
                remove("/tmp/RAW_14BIT_NORMAL.raw");
            } else {
                pobj->devctx.cal_status[2].val = 2;
            }
        }
    } else {
        if (1 == pobj->devctx.cal_status[4].val && 1 == pobj->devctx.cal_status[5].val && (1 != pobj->devctx.cal_status[6].val)) {
            struct stat file_stat;
            time_t prev_mtime; // 之前的修改时间
            time_t current_mtime; // 当前的修改时间
            // 获取文件状态信息
            if (stat("/mnt/mtd/bp_map.table", &file_stat) == -1) {
                perror("stat");
            }
            // 获取之前的修改时间
            prev_mtime = file_stat.st_mtime;

            /* 两点矫正参数保存 */
            execute_command("/mnt/default/thermal_cali1 -c /tmp/config.ini -o /mnt/mtd --bt1data=/tmp/RAW_14BIT_LOW.raw --bt2data=/tmp/RAW_14BIT_HIGH.raw", result);
            
            // 再次获取文件状态信息
            if (stat("/mnt/mtd/bp_map.table", &file_stat) == -1) {
                perror("stat");
            }
            // 获取当前的修改时间
            current_mtime = file_stat.st_mtime;
            if (strstr(result, "calibration successfully") && prev_mtime != current_mtime) {
                pobj->devctx.cal_status[6].val = 1;
                remove("/tmp/RAW_14BIT_LOW.raw");
                remove("/tmp/RAW_14BIT_HIGH.raw");
            } else {
                pobj->devctx.cal_status[6].val = 2;
            }
        }
    }

    return 0;
}

static void *thread_200ms_callback(void *p)
{
    UICtx_t *pobj = (UICtx_t*)p;
    pthread_detach(pthread_self());

    while(1) {
        usleep(200 * 1000);
        Hal_ICM20948(pobj->devctx.compass.val, pobj->devctx.motion.val, &pobj->devctx.compass_angle.val, &pobj->devctx.hori_angle.val, &pobj->devctx.vert_angle.val);
        if (pobj->devctx.img_brightness_tick.val) {
            pobj->devctx.img_brightness_tick.val--;
        }
        if (pobj->devctx.color_mode_tick.val) {
            pobj->devctx.color_mode_tick.val--;
        }
        /* 恢复出厂设置 */
        if (pobj->devctx.factory_reset.val) {
            if (0 == --pobj->devctx.factory_reset.val) {
                hal_sys_factoryset();
            }
        }
        /* 更改分辨率重启 */
        if (pobj->devctx.warning_tick.val) {
            if (0 == --pobj->devctx.warning_tick.val) {
                reboot(RB_AUTOBOOT);
            }
        }
        /* 参数保存 */
        if (pobj->devctx.save_para_tick.val) {
            if (0 == --pobj->devctx.save_para_tick.val) {
                HAL_FPGA_para_save();
                save_all_parameters(0, pobj);
            }
        }
        /* 背景校正 */
        if (pobj->devctx.bg_cal_tick.val) {
            if (0 == --pobj->devctx.bg_cal_tick.val) {
                switch (pobj->devctx.sensor_type.val)
                {
                case TYPE_FPGA_256X192:
                case TYPE_FPGA_384X288:
                case TYPE_FPGA_640X512:
                    HAL_FPGA_background_cal();
                    break;
                default:
                    hal_thermal_bg_cal();
                    break;
                }
            }
        }
    }
    
    return NULL;
}

int create_200ms_thread(UICtx_t *pobj)
{
    pthread_t thread_200ms;
    if (-1 == pthread_create(&thread_200ms, NULL, thread_200ms_callback, pobj)){
        perror("Create thread of thread_200ms");
        return -1;
    }
    return 0;
}

STATE_FUNC_ID setup_nomal = {{
    {KEY1_LONG,                 setup_normal_mainmenu1},
    {KEY2_SHORT,                setup_normal_img_brightness},
    {KEY2_LONG,                 setup_normal_reticle},
    {KEY3_SHORT,                setup_normal_color_mode},
    {KEY4_SHORT,                setup_normal_zoom_dec},
    {KEY5_SHORT,                setup_normal_zoom_inc},
    {KEY4_KEY5_SHORT,           setup_normal_shutter_cal},
    {KEY4_KEY5_LONG,            setup_normal_bg_cal},
    },
};

STATE_FUNC_ID setup_mainmenu1 = {{
    {KEY1_SHORT,                setup_mainmenu1_choice},
    {KEY1_LONG,                 setup_normal_entry},
    {KEY2_SHORT,                setup_mainmenu1_sel_pre},
    {KEY3_SHORT,                setup_mainmenu1_sel_next},
    {KEY_TIMEOUT_30S,           setup_normal_entry},
    },
};

STATE_FUNC_ID setup_image = {{
    {KEY1_SHORT,                setup_image_choice},
    {KEY1_LONG,                 setup_normal_entry},
    {KEY2_SHORT,                setup_sub_menu_sel_pre},
    {KEY3_SHORT,                setup_sub_menu_sel_next},
    {KEY_TIMEOUT_30S,           setup_normal_entry},
    },
};

STATE_FUNC_ID setup_image_adjust = {{
    {KEY1_SHORT,                setup_image_adjust_choice},
    {KEY1_LONG,                 setup_normal_entry},
    {KEY2_SHORT,                setup_image_adjust_sel_pre},
    {KEY3_SHORT,                setup_image_adjust_sel_next},
    {KEY4_SHORT,                setup_image_adjust_dec},
    {KEY5_SHORT,                setup_image_adjust_inc},
    {KEY_TIMEOUT_30S,           setup_normal_entry},
    },
};

STATE_FUNC_ID setup_image_setting = {{
    {KEY1_SHORT,                setup_image_setting_choice},
    {KEY1_LONG,                 setup_normal_entry},
    {KEY2_SHORT,                setup_image_setting_sel_pre},
    {KEY3_SHORT,                setup_image_setting_sel_next},
    {KEY4_SHORT,                setup_image_setting_dec},
    {KEY5_SHORT,                setup_image_setting_inc},
    {KEY_TIMEOUT_30S,           setup_normal_entry},
    },
};

STATE_FUNC_ID setup_camera_setting = {{
    {KEY1_SHORT,                setup_camera_setting_choice},
    {KEY1_LONG,                 setup_normal_entry},
    {KEY2_SHORT,                setup_sub_menu_sel_pre},
    {KEY3_SHORT,                setup_sub_menu_sel_next},
    {KEY4_SHORT,                setup_camera_setting_dec},
    {KEY5_SHORT,                setup_camera_setting_inc},
    {KEY_TIMEOUT_30S,           setup_normal_entry},
    },
};

STATE_FUNC_ID setup_WB_setting = {{
    {KEY1_SHORT,                setup_WB_setting_choice},
    {KEY1_LONG,                 setup_normal_entry},
    {KEY2_SHORT,                setup_WB_setting_sel_pre},
    {KEY3_SHORT,                setup_WB_setting_sel_next},
    {KEY4_SHORT,                setup_WB_setting_dec},
    {KEY5_SHORT,                setup_WB_setting_inc},
    {KEY_TIMEOUT_30S,           setup_normal_entry},
    },
};

STATE_FUNC_ID setup_reticle = {{
    {KEY1_SHORT,                setup_reticle_choice},
    {KEY1_LONG,                 setup_normal_entry},
    {KEY2_SHORT,                setup_reticle_sel_pre},
    {KEY3_SHORT,                setup_reticle_sel_next},
    {KEY4_SHORT,                setup_reticle_switch},
    {KEY5_SHORT,                setup_reticle_switch},
    {KEY_TIMEOUT_30S,           setup_normal_entry},
    },
};

STATE_FUNC_ID setup_cross_color_setting = {{
    {KEY1_SHORT,                setup_cross_color_setting_choice},
    {KEY1_LONG,                 setup_normal_entry},
    {KEY2_SHORT,                setup_cross_color_setting_pre},
    {KEY3_SHORT,                setup_cross_color_setting_next},
    {KEY_TIMEOUT_30S,           setup_normal_entry},
    },
};

STATE_FUNC_ID setup_gun_cal = {{
    {KEY1_LONG,                  setup_gun_cal_save},
    {KEY2_SHORT,                 setup_gun_cal_up},
    {KEY3_SHORT,                 setup_gun_cal_down},
    {KEY4_SHORT,                 setup_gun_cal_left},
    {KEY5_SHORT,                 setup_gun_cal_right},
    {KEY2_LONG_CONT,             setup_gun_cal_up},
    {KEY3_LONG_CONT,             setup_gun_cal_down},
    {KEY4_LONG_CONT,             setup_gun_cal_left},
    {KEY5_LONG_CONT,             setup_gun_cal_right},
    {KEY_TIMEOUT_30S,            setup_normal_entry},
    },
};

STATE_FUNC_ID setup_nine_axis = {{
    {KEY1_SHORT,                 setup_nine_axis_choice},
    {KEY1_LONG,                  setup_normal_entry},
    {KEY2_SHORT,                 setup_sub_menu_sel_pre},
    {KEY3_SHORT,                 setup_sub_menu_sel_next},
    {KEY4_SHORT,                 setup_nine_axis_switch},
    {KEY5_SHORT,                 setup_nine_axis_switch},
    {KEY_TIMEOUT_30S,            setup_normal_entry},
    },
};

STATE_FUNC_ID setup_compass_cal = {{
    {KEY1_SHORT,                setup_compass_cal_exit},
    },
};

STATE_FUNC_ID setup_system = {{
    {KEY1_SHORT,                 setup_system_choice},
    {KEY1_LONG,                  setup_normal_entry},
    {KEY2_SHORT,                 setup_sub_menu_sel_pre},
    {KEY3_SHORT,                 setup_sub_menu_sel_next},
    {KEY_TIMEOUT_30S,            setup_normal_entry},
    },
};

STATE_FUNC_ID setup_language = {{
    {KEY1_SHORT,                 setup_language_choice},
    {KEY1_LONG,                  setup_normal_entry},
    {KEY2_SHORT,                 setup_sub_menu_sel_pre},
    {KEY3_SHORT,                 setup_sub_menu_sel_next},
    {KEY_TIMEOUT_30S,            setup_normal_entry},
    },
};

STATE_FUNC_ID setup_factory_reset = {{
    {KEY1_SHORT,                setup_factory_reset_choice},
    {KEY1_LONG,                 setup_normal_entry},
    {KEY2_SHORT,                setup_factory_reset_sel_pre},
    {KEY3_SHORT,                setup_factory_reset_sel_next},
    {KEY_TIMEOUT_30S,           setup_normal_entry},
    },
};

STATE_FUNC_ID setup_ver_info = {{
    {KEY1_SHORT,                setup_ver_info_exit},
    {KEY1_LONG,                 setup_normal_entry},
    {KEY2_SHORT,                setup_engineering_enter},
    {KEY_TIMEOUT_30S,           setup_normal_entry},
    },
};

STATE_FUNC_ID setup_engineering = {{
    {KEY2_SHORT,                setup_engineering_exit},
    {KEY4_SHORT,                setup_engineering_sel_pre},
    {KEY5_SHORT,                setup_engineering_sel_next},
    {KEY2_KEY3_LONG,            setup_engineering_save_para},
    {KEY4_KEY5_LONG,            setup_engineering_get_para},
    },
};

static UICtx_t gUICtx = {0};
UICtx_t *getUICtx(void)
{
    return &gUICtx;
}

void Construct_menuctx(UICtx_t *pobj)
{
    int i = 0;

    pobj->devctx.mainmenu1.node[i++] = &pobj->devctx.image;
    if (TYPE_VIS_1920X1080 == pobj->devctx.sensor_type.val) {
        pobj->devctx.mainmenu1.node[i++] = &pobj->devctx.camera_setting;
    }
    pobj->devctx.mainmenu1.node[i++] = &pobj->devctx.reticle;
    pobj->devctx.mainmenu1.node[i++] = &pobj->devctx.nine_axis;
    pobj->devctx.mainmenu1.node[i++] = &pobj->devctx.menu_system;
    pobj->devctx.mainmenu1.node[i++] = &pobj->devctx.menu_exit;
    pobj->devctx.mainmenu1.curnode.min = 0;
    pobj->devctx.mainmenu1.curnode.max = i - 1;
    pobj->devctx.mainmenu1.curnode.val = 0;

    i = 0;
    pobj->devctx.image_adjust.node[i++] = &pobj->devctx.img_brightness;
    pobj->devctx.image_adjust.node[i++] = &pobj->devctx.img_contrast;
    // pobj->devctx.image_adjust.node[i++] = &pobj->devctx.img_detail_enhance;
    // pobj->devctx.image_adjust.node[i++] = &pobj->devctx.img_gamma;
    pobj->devctx.image_adjust.node[i++] = &pobj->devctx.img_sharpness;
    pobj->devctx.image_adjust.node[i++] = &pobj->devctx.img_3D_denoise;
    pobj->devctx.image_adjust.node[i++] = &pobj->devctx.img_2D_denoise;
    pobj->devctx.image_adjust.node[i++] =  NULL;    // return
    pobj->devctx.image_adjust.curnode.min = 0;
    pobj->devctx.image_adjust.curnode.max = i - 1;
    pobj->devctx.image_adjust.curnode.val = 0;

    i = 0;
    pobj->devctx.image_setting.node[i++] = &pobj->devctx.image_miror;
    pobj->devctx.image_setting.node[i++] = &pobj->devctx.image_flip;
    pobj->devctx.image_setting.node[i++] = &pobj->devctx.EIS;
    pobj->devctx.image_setting.node[i++] = NULL;    // return
    pobj->devctx.image_setting.curnode.min = 0;
    pobj->devctx.image_setting.curnode.max = i - 1;
    pobj->devctx.image_setting.curnode.val = 0;
}

int Init_UICtx(UICtx_t *pobj)
{
    int para_tmp;
    gpio_init();
    pobj->curid = id_normal;

    load_oeminfo_from_flash("OEM_MODEL_NAME", pobj->sys_info.model_name, 16);
    char vi_sensor_type[16];
    load_oeminfo_from_flash("bt6560_res", vi_sensor_type, 16);
    switch (atoi(vi_sensor_type))
    {
    case 1:
        pobj->devctx.sensor_type.val = TYPE_FPGA_384X288;
        pobj->res_info.sensor_width = 384;
        pobj->res_info.sensor_height = 288;
        break;
    case 3:
        pobj->devctx.sensor_type.val = TYPE_FPGA_640X512;
        pobj->res_info.sensor_width = 640;
        pobj->res_info.sensor_height = 512;
        break;
    case 53:
        pobj->devctx.sensor_type.val = TYPE_FPGA_256X192;
        pobj->res_info.sensor_width = 256;
        pobj->res_info.sensor_height = 192;
        break;
    case 45:
        pobj->devctx.sensor_type.val = TYPE_SENSOR_640X512;
        pobj->res_info.sensor_width = 640;
        pobj->res_info.sensor_height = 512;
        break;
    default:    // 40
        pobj->devctx.sensor_type.val = TYPE_SENSOR_384X288;
        pobj->res_info.sensor_width = 384;
        pobj->res_info.sensor_height = 288;
        break;
    }

    if (strstr(pobj->sys_info.model_name, "A1D")) {
        pobj->devctx.sensor_type.val = TYPE_VIS_1920X1080;
        pobj->res_info.sensor_width = 1920;
        pobj->res_info.sensor_height = 1080;
    }
    Construct_menuctx(pobj);

    char lcd_width[16], lcd_height[16];
    load_oeminfo_from_flash("lcd_width", lcd_width, 16);
    load_oeminfo_from_flash("lcd_height", lcd_height, 16);
    pobj->res_info.osd_width = atoi(lcd_width);
    pobj->res_info.osd_height = atoi(lcd_height);

    if (1024 == pobj->res_info.osd_width && 768 == pobj->res_info.osd_height) {
        pobj->devctx.cross_type.val = 1;
        pobj->devctx.output_res_type.val = OUTPUT_RES_1024X768;
    } else if (1280 == pobj->res_info.osd_width && 720 == pobj->res_info.osd_height) {
        pobj->devctx.cross_type.val = 2;
        pobj->devctx.output_res_type.val = OUTPUT_RES_1280X720;
    } else if (1280 == pobj->res_info.osd_width && 1024 == pobj->res_info.osd_height) {
        pobj->devctx.cross_type.val = 3;
        pobj->devctx.output_res_type.val = OUTPUT_RES_1280X1024;
    } else if (1920 == pobj->res_info.osd_width && 1080 == pobj->res_info.osd_height) {
        pobj->devctx.cross_type.val = 4;
        pobj->devctx.output_res_type.val = OUTPUT_RES_1920X1080;
    } else {
        pobj->devctx.cross_type.val = 0;
        pobj->devctx.output_res_type.val = OUTPUT_RES_720X480;
    }

    pobj->w_zoom = (float)pobj->res_info.osd_width / 720;
    pobj->h_zoom = (float)pobj->res_info.osd_height / 480;

    pobj->devctx.img_brightness.nid = nid_image_adjust_brightness;
    pobj->devctx.img_brightness.min = 0;
    pobj->devctx.img_brightness.max = 10;
    pobj->devctx.img_brightness.val = 5;
    if (0 == hal_get_para(PARA_TM_BRIGHTNESS, &para_tmp)) {
        pobj->devctx.img_brightness.val = para_tmp;
    }
    // TODO:图像亮度
    switch (pobj->devctx.sensor_type.val)
    {
    case TYPE_VIS_1920X1080:
        hal_cs_set_brightness(pobj->devctx.img_brightness.val * 20);
        break;
    case TYPE_FPGA_256X192:
    case TYPE_FPGA_384X288:
    case TYPE_FPGA_640X512:
        HAL_FPGA_brightness(pobj->devctx.img_brightness.val);
        break;
    default:
        hal_thermal_set_bright(pobj->devctx.img_brightness.val);
        break;
    }

    pobj->devctx.img_contrast.nid = nid_image_adjust_contrast;
    pobj->devctx.img_contrast.min = 0;
    pobj->devctx.img_contrast.max = 10;
    pobj->devctx.img_contrast.val = 5;
    if (0 == hal_get_para(PARA_TM_CONTRAST, &para_tmp)) {
        pobj->devctx.img_contrast.val = para_tmp;
    }
    // TODO:图像对比度
    switch (pobj->devctx.sensor_type.val)
    {
    case TYPE_VIS_1920X1080:
        hal_cs_set_contrast(pobj->devctx.img_contrast.val * 20);
        break;
    case TYPE_FPGA_256X192:
    case TYPE_FPGA_384X288:
    case TYPE_FPGA_640X512:
        HAL_FPGA_contrast(pobj->devctx.img_contrast.val);
        break;
    default:
        hal_thermal_set_contrast(pobj->devctx.img_contrast.val);
        break;
    }

    pobj->devctx.img_sharpness.nid = nid_image_adjust_sharpness;
    pobj->devctx.img_sharpness.min = 0;
    pobj->devctx.img_sharpness.max = 10;
    pobj->devctx.img_sharpness.val = 5;
    if (0 == hal_get_para(PARA_TM_SHARPNESS, &para_tmp)) {
        pobj->devctx.img_sharpness.val = para_tmp;
    }
    // TODO:图像锐度
    switch (pobj->devctx.sensor_type.val)
    {
    case TYPE_VIS_1920X1080:
        hal_cs_set_sharpness(pobj->devctx.img_sharpness.val * 40);
        break;
    case TYPE_FPGA_256X192:
    case TYPE_FPGA_384X288:
    case TYPE_FPGA_640X512:
        HAL_FPGA_detail_enhance(pobj->devctx.img_sharpness.val);
        break;
    default:
        hal_thermal_set_sharpness(pobj->devctx.img_sharpness.val);
        break;
    }

    pobj->devctx.language.nid = nid_null;
    pobj->devctx.language.min = 0;
    pobj->devctx.language.max = 1;
    pobj->devctx.language.val = 0;   // default:0 英语
    if (0 == hal_get_para(PARA_LANGUAGE, &para_tmp)) {
        pobj->devctx.language.val = para_tmp;
    }

    pobj->devctx.zoom.nid = nid_null;
    pobj->devctx.zoom.min = 0;
    pobj->devctx.zoom.max = 3;
    pobj->devctx.zoom.val = 0;  // default:0 1x

    if (TYPE_VIS_1920X1080 != pobj->devctx.sensor_type.val) {
        pobj->devctx.color_mode.nid = nid_null;
        pobj->devctx.color_mode.min = 0;
        pobj->devctx.color_mode.max = 5;
        pobj->devctx.color_mode.val = 0;    // default:0 黑热
        if (0 == hal_get_para(PARA_COLOR_MODE, &para_tmp)) {
            pobj->devctx.color_mode.val = para_tmp;
        }
        // TODO:设置图像模式
        switch (pobj->devctx.sensor_type.val)
        {
        case TYPE_FPGA_256X192:
        case TYPE_FPGA_384X288:
        case TYPE_FPGA_640X512:
            HAL_FPGA_colormode(pobj->devctx.color_mode.val);
            break;
        default:
            hal_thermal_color_mode(pobj->devctx.color_mode.val);
            break;
        }
    }

    // pobj->devctx.img_detail_enhance.nid = nid_image_adjust_sharpness;
    // pobj->devctx.img_detail_enhance.min = 0;
    // pobj->devctx.img_detail_enhance.max = 10;
    // pobj->devctx.img_detail_enhance.val = 5;
    // if (0 == hal_get_para(PARA_TM_DETAIL_ENHANCE, &para_tmp)) {
    //     pobj->devctx.img_detail_enhance.val = para_tmp;
    // }
    // // TODO:设置图像细节增强
    // if (TYPE_VIS_1920X1080 == pobj->devctx.sensor_type.val) {

    // } else {
    //     hal_thermal_set_sharpness(pobj->devctx.img_detail_enhance.val);
    // }

    pobj->devctx.img_3D_denoise.nid = nid_image_adjust_img_3D_denoise;
    pobj->devctx.img_3D_denoise.min = 0;
    pobj->devctx.img_3D_denoise.max = 10;
    pobj->devctx.img_3D_denoise.val = 5;
    if (0 == hal_get_para(PARA_TM_3D_DENOISE, &para_tmp)) {
        pobj->devctx.img_3D_denoise.val = para_tmp;
    }
    // TODO:设置时域降噪
    switch (pobj->devctx.sensor_type.val)
    {
    case TYPE_VIS_1920X1080:
        hal_cs_set_3Ddenoiselevel(pobj->devctx.img_3D_denoise.val * 40);
        break;
    case TYPE_FPGA_256X192:
    case TYPE_FPGA_384X288:
    case TYPE_FPGA_640X512:
        HAL_FPGA_time_domain_denoise(pobj->devctx.img_3D_denoise.val);
        break;
    default:
        hal_thermal_set_3Ddenoiselevel(pobj->devctx.img_3D_denoise.val);
        break;
    }

    pobj->devctx.img_2D_denoise.nid = nid_image_adjust_img_2D_denoise;
    pobj->devctx.img_2D_denoise.min = 0;
    pobj->devctx.img_2D_denoise.max = 10;
    pobj->devctx.img_2D_denoise.val = 5;
    if (0 == hal_get_para(PARA_TM_2D_DENOISE, &para_tmp)) {
        pobj->devctx.img_2D_denoise.val = para_tmp;
    }
    // TODO:设置空域降噪
    switch (pobj->devctx.sensor_type.val)
    {
    case TYPE_VIS_1920X1080:
        hal_cs_set_2Ddenoiselevel(pobj->devctx.img_2D_denoise.val * 40);
        break;
    case TYPE_FPGA_256X192:
    case TYPE_FPGA_384X288:
    case TYPE_FPGA_640X512:
        HAL_FPGA_Space_domain_denoise(pobj->devctx.img_2D_denoise.val);
        break;
    default:
        hal_thermal_set_2Ddenoiselevel(pobj->devctx.img_2D_denoise.val);
        break;
    }

    // pobj->devctx.img_gamma.nid = nid_image_adjust_gamma;
    // pobj->devctx.img_gamma.min = 0;
    // pobj->devctx.img_gamma.max = 10;
    // pobj->devctx.img_gamma.val = 5;
    // if (0 == hal_get_para(PARA_TM_GAMMA, &para_tmp)) {
    //     pobj->devctx.img_gamma.val = para_tmp;
    // }
    // // TODO:设置gamma
    // if (TYPE_VIS_1920X1080 == pobj->devctx.sensor_type.val) {

    // } else {
    //     hal_thermal_set_gamma(pobj->devctx.img_gamma.val);
    // }

    pobj->devctx.image_miror.nid = nid_image_setting_mirror;
    pobj->devctx.image_miror.min = 0;
    pobj->devctx.image_miror.max = 1;
    pobj->devctx.image_miror.val = 0;
    if (0 == hal_get_para(PARA_TM_MIRROR, &para_tmp)) {
        pobj->devctx.image_miror.val = para_tmp;
    }
    // TODO:设置图像镜像
    switch (pobj->devctx.sensor_type.val)
    {
    case TYPE_VIS_1920X1080:
        /* code */
        break;
    case TYPE_FPGA_256X192:
    case TYPE_FPGA_384X288:
    case TYPE_FPGA_640X512:
        HAL_FPGA_mirror(pobj->devctx.image_miror.val);
        break;
    default:
        hal_thermal_mirror(pobj->devctx.image_miror.val);
        break;
    }

    pobj->devctx.image_flip.nid = nid_image_setting_flip;
    pobj->devctx.image_flip.min = 0;
    pobj->devctx.image_flip.max = 1;
    pobj->devctx.image_flip.val = 0;
    if (0 == hal_get_para(PARA_TM_FLIP, &para_tmp)) {
        pobj->devctx.image_flip.val = para_tmp;
    }
    // TODO:设置图像反转
    switch (pobj->devctx.sensor_type.val)
    {
    case TYPE_VIS_1920X1080:
        /* code */
        break;
    case TYPE_FPGA_256X192:
    case TYPE_FPGA_384X288:
    case TYPE_FPGA_640X512:
        HAL_FPGA_flip(pobj->devctx.image_flip.val);
        break;
    default:
        hal_thermal_flip(pobj->devctx.image_flip.val);
        break;
    }

    pobj->devctx.EIS.nid = nid_image_setting_EIS;
    pobj->devctx.EIS.min = 0;
    pobj->devctx.EIS.max = 1;
    pobj->devctx.EIS.val = 1;
    if (0 == hal_get_para(PARA_TM_EIS, &para_tmp)) {
        pobj->devctx.EIS.val = para_tmp;
    }
    // TODO:设置电子防抖
    switch (pobj->devctx.sensor_type.val)
    {
    case TYPE_VIS_1920X1080:
        break;
    case TYPE_FPGA_256X192:
    case TYPE_FPGA_384X288:
    case TYPE_FPGA_640X512:
        break;
    default:
        hal_thermal_eis(pobj->devctx.EIS.val, 0, 0, 0);
        break;
    }

    if (TYPE_VIS_1920X1080 == pobj->devctx.sensor_type.val) {
        pobj->devctx.VIS_mode.nid = nid_null;
        pobj->devctx.VIS_mode.min = 0;
        pobj->devctx.VIS_mode.max = 2;
        pobj->devctx.VIS_mode.val = 0;
        if (0 == hal_get_para(PARA_VIS_MODE, &para_tmp)) {
            pobj->devctx.VIS_mode.val = para_tmp;
        }
        // TODO:设置可见光模式
        switch ( pobj->devctx.VIS_mode.val)
        {
        case 0:
            pobj->devctx.VIS_sensor_fps.val = 50;
            IRCUT_init(0);
            hal_cs_set_brightness(100);
            hal_cs_set_capmode(1, pobj->devctx.VIS_sensor_fps.val);
            hal_cs_set_shutter(40000, pobj->devctx.VIS_sensor_fps.val);
            break;
        case 1:
            pobj->devctx.VIS_sensor_fps.val = 25;
            IRCUT_init(1);
            hal_cs_set_brightness(120);
            hal_cs_set_capmode(1, pobj->devctx.VIS_sensor_fps.val);
            hal_cs_set_shutter(40000, pobj->devctx.VIS_sensor_fps.val);
            break;
        case 2:
            pobj->devctx.VIS_sensor_fps.val = 50;
            IRCUT_init(1);
            hal_cs_set_brightness(100);
            hal_cs_set_capmode(1, pobj->devctx.VIS_sensor_fps.val);
            hal_cs_set_shutter(40000, pobj->devctx.VIS_sensor_fps.val);
            break;
        }

        pobj->devctx.EC.nid = nid_null;
        pobj->devctx.EC.min = 0;
        pobj->devctx.EC.max = 12;
        pobj->devctx.EC.val = 6;
        if (0 == hal_get_para(PARA_EC, &para_tmp)) {
            pobj->devctx.EC.val = para_tmp;
        }
        // TODO:设置曝光补偿
        hal_cs_set_ev(25 + pobj->devctx.EC.val * 31);

        pobj->devctx.WDR.nid = nid_null;
        pobj->devctx.WDR.min = 0;
        pobj->devctx.WDR.max = 2;
        pobj->devctx.WDR.val = 1;
        if (0 == hal_get_para(PARA_WDR, &para_tmp)) {
            pobj->devctx.WDR.val = para_tmp;
        }
        // TODO:设置宽动态

        pobj->devctx.WB_mode.nid = nid_null;
        pobj->devctx.WB_mode.min = 0;
        pobj->devctx.WB_mode.max = 1;
        pobj->devctx.WB_mode.val = 0;
        if (0 == hal_get_para(PARA_WB_MODE, &para_tmp)) {
            pobj->devctx.WB_mode.val = para_tmp;
        }
        // TODO:设置白平衡

        pobj->devctx.color_temp.nid = nid_null;
        pobj->devctx.color_temp.min = 0;
        pobj->devctx.color_temp.max = 2;
        pobj->devctx.color_temp.val = 1;
        if (0 == hal_get_para(PARA_COLOR_TEMP, &para_tmp)) {
            pobj->devctx.color_temp.val = para_tmp;
        }
        // TODO:设置色温
        switch (pobj->devctx.color_temp.val)
        {
        case 0:
            hal_cs_set_hue(-90);
            break;
        case 1:
            hal_cs_set_hue(90);
            break;
        case 2:
            hal_cs_set_hue(360);
            break;
        }
    }

    pobj->devctx.cross_pos.center_x.nid = nid_null;
    pobj->devctx.cross_pos.center_x.min = -(pobj->res_info.sensor_width / 4);
    pobj->devctx.cross_pos.center_x.max = pobj->res_info.sensor_width / 4;
    pobj->devctx.cross_pos.center_x.val = 0;
    if (0 == hal_get_para(PARA_CROSS_POS_X, &para_tmp)) {
        pobj->devctx.cross_pos.center_x.val = para_tmp;
    }

    pobj->devctx.cross_pos.center_y.nid = nid_null;
    pobj->devctx.cross_pos.center_y.min = -(pobj->res_info.sensor_height / 4);
    pobj->devctx.cross_pos.center_y.max = pobj->res_info.sensor_height / 4;
    pobj->devctx.cross_pos.center_y.val = 0;
    if (0 == hal_get_para(PARA_CROSS_POS_Y, &para_tmp)) {
        pobj->devctx.cross_pos.center_y.val = para_tmp;
    }

    pobj->devctx.reticle.nid = nid_menu_reticle;
    pobj->devctx.reticle.min = 0;
    pobj->devctx.reticle.max = 1;
    pobj->devctx.reticle.val = 0;
    if (0 == hal_get_para(PARA_RETICLE, &para_tmp)) {
        pobj->devctx.reticle.val = para_tmp;
    }

    pobj->devctx.cross_color.nid = nid_null;
    pobj->devctx.cross_color.min = 0;
    pobj->devctx.cross_color.max = 3;
    pobj->devctx.cross_color.val = 0;
    if (0 == hal_get_para(PARA_CROSS_COLOR, &para_tmp)) {
        pobj->devctx.cross_color.val = para_tmp;
    }
    if (pobj->devctx.reticle.val) {
        hal_cross_update(1, pobj->devctx.cross_type.val, pobj->devctx.cross_color.val, pobj->devctx.cross_pos.center_x.val, pobj->devctx.cross_pos.center_y.val);
    }
    pobj->devctx.compass.nid = nid_null;
    pobj->devctx.compass.min = 0;
    pobj->devctx.compass.max = 1;
    pobj->devctx.compass.val = 0;
    if (0 == hal_get_para(PARA_COMPASS, &para_tmp)) {
        pobj->devctx.compass.val = para_tmp;
    }

    pobj->devctx.motion.nid = nid_null;
    pobj->devctx.motion.min = 0;
    pobj->devctx.motion.max = 1;
    pobj->devctx.motion.val = 0;
    if (0 == hal_get_para(PARA_MOTION, &para_tmp)) {
        pobj->devctx.motion.val = para_tmp;
    }

    pobj->devctx.nine_axis.nid = nid_menu_nine_axis_setting;
    pobj->devctx.nine_axis.min = 0;
    pobj->devctx.nine_axis.max = 2;
    pobj->devctx.nine_axis.val = 0;

    pobj->devctx.camera_setting.nid = nid_menu_camera_setting;
    pobj->devctx.camera_setting.min = 0;
    pobj->devctx.camera_setting.max = nid_camera_setting_end;
    pobj->devctx.camera_setting.val = 0;

    pobj->devctx.menu_system.nid = nid_menu_system;
    pobj->devctx.menu_exit.nid = nid_menu_exit;

    // hal_wifi_onoff(1);

    return 0;
}

/*******************************************************	
    handle_event
    事件处理中心, 程序运行的核心函数，输入事件，跟新状态
    
    input:   		pobj   设备句柄
                    keyval 按键驱动
    output  :       1: 需要跟新UI显示
                    0: 无需跟新UI显示
    输出给GUI,  决策GUI是否需要跟新handle_gui();
********************************************************/
int handle_event(UICtx_t *pobj, eKeyVal keyval)
{
    int i;
    int ret =0;

    switch(pobj->curid)
    {
    case id_normal:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_nomal.func_id[i].keyval == keyval) {
                if (setup_nomal.func_id[i].func_ptr) {
                    setup_nomal.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_mainmenu1:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_mainmenu1.func_id[i].keyval == keyval) {
                if (setup_mainmenu1.func_id[i].func_ptr) {
                    setup_mainmenu1.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_image:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_image.func_id[i].keyval == keyval) {
                if (setup_image.func_id[i].func_ptr) {
                    setup_image.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_image_adjust:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_image_adjust.func_id[i].keyval == keyval) {
                if (setup_image_adjust.func_id[i].func_ptr) {
                    setup_image_adjust.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_image_setting:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_image_setting.func_id[i].keyval == keyval) {
                if (setup_image_setting.func_id[i].func_ptr) {
                    setup_image_setting.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_camera_setting:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_camera_setting.func_id[i].keyval == keyval) {
                if (setup_camera_setting.func_id[i].func_ptr) {
                    setup_camera_setting.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_WB_setting:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_WB_setting.func_id[i].keyval == keyval) {
                if (setup_WB_setting.func_id[i].func_ptr) {
                    setup_WB_setting.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_reticle:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_reticle.func_id[i].keyval == keyval) {
                if (setup_reticle.func_id[i].func_ptr) {
                    setup_reticle.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_cross_color_setting:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_cross_color_setting.func_id[i].keyval == keyval) {
                if (setup_cross_color_setting.func_id[i].func_ptr) {
                    setup_cross_color_setting.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_gun_cal:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_gun_cal.func_id[i].keyval == keyval) {
                if (setup_gun_cal.func_id[i].func_ptr) {
                    setup_gun_cal.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_nine_axis_setting:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_nine_axis.func_id[i].keyval == keyval) {
                if (setup_nine_axis.func_id[i].func_ptr) {
                    setup_nine_axis.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_compass_cal:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_compass_cal.func_id[i].keyval == keyval) {
                if (setup_compass_cal.func_id[i].func_ptr) {
                    setup_compass_cal.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_system:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_system.func_id[i].keyval == keyval) {
                if (setup_system.func_id[i].func_ptr) {
                    setup_system.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_language:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_language.func_id[i].keyval == keyval) {
                if (setup_language.func_id[i].func_ptr) {
                    setup_language.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_factory_reset:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_factory_reset.func_id[i].keyval == keyval) {
                if (setup_factory_reset.func_id[i].func_ptr) {
                    setup_factory_reset.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_ver_info:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_ver_info.func_id[i].keyval == keyval) {
                if (setup_ver_info.func_id[i].func_ptr) {
                    setup_ver_info.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    case id_engineering:
        for (i = 0; i < KEY_NULL; i++) {
            if (setup_engineering.func_id[i].keyval == keyval) {
                if (setup_engineering.func_id[i].func_ptr) {
                    setup_engineering.func_id[i].func_ptr(pobj);
                    ret = 1;
                }
            }
        }
        break;
    }

    return ret;
}